/*
File ResXXXXEd.c

Copyright Apple Computer, Inc. 1985-1989
All rights reserved.
*/

#include	<types.h>
#include	<memory.h>
#include	<menus.h>
#include	<resources.h>

#include	"ResEd.h"

#define windowWidth 300
#define windowHeight 100
#define deleteChr 8
#define sizeOfMyResource 10

typedef struct rXXXXRec {
	ParentHandle	father; 	/* Back ptr to dad */
	Str64			name;		/* The name of this editor */
	WindowPtr		windPtr;	/* This view's window */
	Boolean			rebuild;	/* Set true if things have changed */
	Handle			hXXXX;		/* The resource we are working on */
} rXXXXRec;

typedef	rXXXXRec	*rXXXXPtr;
typedef	rXXXXPtr	*rXXXXHandle;

/* Function prototypes. */
pascal void DoMenu(short menu, short item, rXXXXHandle myXXXX);


/*- -	-  -  - -  -  -  - -  -  -	- -  -	-  - -	-  -  - -  -  -*/

/* Fix up the window name and title for our window. */
void GetNameAndTitle (StringPtr windowTitle, StringPtr windowName, Handle thing)
{	
	strcpy(windowTitle, "\pXXXX");
	SetETitle(thing, windowTitle);
	strncpy(windowName, windowTitle, *windowTitle + 1);	/* Add 1 for the length byte */
}

/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

pascal void EditBirth(Handle thing, ParentHandle dad)
{
	rXXXXHandle	myXXXX;
	rXXXXPtr	p;
	WindowPtr	myWindow;
	Str255		windowTitle,
				newName;

	/* Prepare window title and request creation of a new window */
	GetNameAndTitle (&windowTitle, &newName, thing);
	myWindow = EditorWindSetup(false, windowWidth, windowHeight, &windowTitle, &newName, true, dad);
	
	/* If we got a new window, then start up the editor */
	if (myWindow != NULL) {
		if ((GetHandleSize(thing)) == 0) {  /* This was called via a NEW, so make a new resource. */
			FixHand(sizeOfMyResource, thing);
		}

		/* Get memory for and handle to our instance record */
		myXXXX = (rXXXXHandle)NewHandle(sizeof(rXXXXRec));
		BubbleUp((Handle)myXXXX);
		HLock((Handle)myXXXX);
		
		p = *myXXXX;
		
		/* Put information about this incarnation of the editor and the window it is */
		/* serving into our record.(always passed around in the handle myXXXX).		 */

		p->windPtr = myWindow;
		p->father = dad;
		
		/* Use memcpy here since the editorNameChr is a null and would stop strncpy. */
		memcpy(p->name, &newName, newName[0] + 1);	/* Add 1 for the length byte */
		p->hXXXX = thing;

		/* Let the main program know who is to manage this window by giving it both	*/
		/* our resource ID number and our instance record handle.					*/
		((WindowPeek)myWindow)->windowKind = ResEdID();
		((WindowPeek)myWindow)->refCon = (long)myXXXX;

		/* Set up any menus,views, etc. for this window here. */
		
		HUnlock((Handle)myXXXX);
	}
}

/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

/* Not used for editors. */
pascal void PickBirth(ResType t,ParentHandle dad)
{
	#pragma	unused (t, dad)
}

/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

pascal void DoEvent(EventRecord *evt, rXXXXHandle myXXXX)
{
	Point	mousePoint;

	BubbleUp((Handle)myXXXX);		/* Move our item up in memory */
	HLock((Handle)myXXXX);			/* Lock it down */
	
	/* Handle event passed to us by main program.  Just like a 'real' event loop, exceptÉ	*/
	/*  there is no loop and we don't have to handle as much because the main program		*/
	/*  will do all the stuff that doesn't apply to us.										*/
	
	mousePoint = evt->where;		/* Point at which the event occured */
	SetPort((*myXXXX)->windPtr);	/* Set the port to our window */
	GlobalToLocal(&mousePoint);		/* Convert event location to local coords */
	
	switch (evt->what) {
		case mouseDown:
			break;					/* Do any special mouse down processing here. */

		case activateEvt: 
			AbleMenu(fileMenu, fileTop);
			if (evt->modifiers & activeFlag) {
									/* Do any activate processing here (such as inserting a menu) */
			}
			else {
									/* Do any deactivate processing here (such as deleting a menu). */
			}
			
			DrawMenuBar();			/* To make sure that everything is drawn properly if you are	*/
									/* installing a menu. */
			break;

		case updateEvt:
									/* Do the appropriate update processing here.  Remember that */
									/* BeginUpdate has already been called. */
			PaintRect(&(*myXXXX)->windPtr->portRect);
			break;

		case keyDown:
									/* Do any key processing here. */
					
			/* Convert the delete character into a clear command. */
			if ((evt->message & charCodeMask) == deleteChr) {
				DoMenu(editMenu, clearItem, myXXXX);
			}

			break;

		case nullEvent:
									/* Do any null event processing here (such as blinking a cursor).	*/
			break;
	}
	HUnlock((Handle)myXXXX);
}
/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

pascal void DoInfoUpdate(short oldID, short newID, rXXXXHandle myXXXX)
{
	Str255	windowTitle,
			windowName;

	/* Since our ID has changed, we need to change our window title */
	GetNameAndTitle (&windowTitle, &windowName, (Handle)((*myXXXX)->hXXXX));
	GetWindowTitle (&windowTitle, &windowName, true, (*myXXXX)->father);
	
	/* Save the new name in my data structure. */
	/* Use memcpy here since the editorNameChr is a null and would stop strncpy. */
	memcpy((*myXXXX)->name, &windowName, windowName[0] + 1);	/* Add 1 for the length byte. */
	
	SetWTitle((*myXXXX)->windPtr, &windowTitle);				/* Set the new window title. */

	/* Now, let our father object know that our ID has been changed */
	(*((*myXXXX)->father))->rebuild = true;						/* Rebuild the picker list. */
	CallInfoUpdate(oldID, newID, (*((*myXXXX)->father))->wind->refCon,
				   (*((*myXXXX)->father))->wind->windowKind);
}

/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

/* Close down the window and get rid of any memory that has been allocated. */
static void DoClose(rXXXXHandle myXXXX)
{
	CloseWindow((*myXXXX)->windPtr);
	WindReturn((*myXXXX)->windPtr);		/* Mark the window record as being available */
	SetTheCursor(arrowCursor);			/* Make sure the cursor is the arrow cursor */
	
	/* Delete any menus that we added and redraw the menu bar.	*/
	/* Be sure to dispose of any handles you are done with.		*/

	/* Release the resource if we were launched from a picker. */
	if ((*((*myXXXX)->father))->name[1] != editorNameChr) {
		ReleaseResource ((Handle)(*myXXXX)->hXXXX);  			/* Let it be free (if it is not changed)! */
	}

	DisposHandle((Handle)myXXXX);
}

/*- -  -  -	- -  -	-  - -	-  -  - -  -  -  - -  -  -	- -  -	-*/

pascal void DoMenu(short menu, short item, rXXXXHandle myXXXX)
{
	short	saveRefNum;
	Handle	hTemp;

	BubbleUp((Handle)myXXXX);
	HLock((Handle)myXXXX);
	SetPort((*myXXXX)->windPtr);		/* Set the port to our window */

	/* Again, we handle the menu stuff just as we would in a 'real' application	*/
	/* except that we only have to handle those items that apply to our editor.	*/
	
	switch (menu) {
		case fileMenu:
			switch (item) {
				case closeItem:
					DoClose(myXXXX);	/* Close our window						*/
					return;				/* Return immediately since our resource is gone! */
					
				case saveItem:			/* Pass the save on to other windows.	*/
					PassMenu (fileMenu, saveItem, (ParentHandle)myXXXX);
					break;
		
				case revertItem:
					if (NeedToRevert ((*myXXXX)->windPtr, (Handle)(*myXXXX)->hXXXX)) {
						/* The area under the window will need to be updated 		*/
						InvalRect(&(*myXXXX)->windPtr->portRect);
						
						/* We will need to restore the current resource file		*/
						/* reference number when we are done here.					*/
						saveRefNum = CurrentRes();
						
						/* We are going to be using the resource file we came from.	*/
						UseResFile(HomeResFile((Handle)(*myXXXX)->hXXXX));
						
						/* Read in the old copy from disk (see documentation for 	*/
						/* revertResource).  Clear it out unless this was a newly 	*/
						/* created resource.										*/
						if (!RevertResource((Handle)(*myXXXX)->hXXXX)) {
							/* The resource was newly added so we need to remove it.*/
							
							/* Save the handle so that we can dispose it later. */
							hTemp = (Handle)(*myXXXX)->hXXXX;
							
							/* Make sure that the picker list is rebuilt to remove	*/
							/* this item. 											*/
							(*((*myXXXX)->father))->rebuild = true;
							
							DoClose(myXXXX);		/* Close the window.			*/
							RemoveResource(hTemp);	/* Dispose the resource itself. */
							return;					/* Since the resource is gone.	*/
						}
						/* Go back to using the old resource file.					*/
						UseResFile(saveRefNum);
					}
					break;
					
				case getInfoItem:
					/* Put up the GetInfo window.								*/
					ShowInfo((Handle)(*myXXXX)->hXXXX, (ParentHandle)myXXXX);
					break;
			}

		case editMenu:
				/* Implement the edit menu here. 								*/
			switch (item) {
				case cutItem:	break;
				case copyItem:	break;
				case pasteItem:	break;
				case clearItem:	break;
			}
	}
}
